package xyz.yuzegod.megawalls.classes.novice.enderman;

import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.Sound;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType;
import org.bukkit.scheduler.BukkitRunnable;
import xyz.yuzegod.megawalls.MegaWalls;
import xyz.yuzegod.megawalls.classes.Classes;
import xyz.yuzegod.megawalls.classes.Skill;
import xyz.yuzegod.megawalls.game.GamePlayer;
import xyz.yuzegod.megawalls.stats.KitStatsContainer;
import xyz.yuzegod.megawalls.util.LocationUtils;
import xyz.yuzegod.megawalls.util.ParticleEffect;
import xyz.yuzegod.megawalls.util.PlayerUtils;
import xyz.yuzegod.megawalls.util.StringUtils;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

public class MainSkill extends Skill
{
    private static final Set<Material> set;
    
    public MainSkill(final Classes classes) {
        super("瞬移", classes);
    }
    
    @Override
    public int maxedLevel() {
        return 5;
    }
    
    @Override
    public double getAttribute(final int level) {
        switch (level) {
            case 1: {
                return 13.0;
            }
            case 2: {
                return 16.0;
            }
            case 3: {
                return 19.0;
            }
            case 4: {
                return 22.0;
            }
            case 5: {
                return 25.0;
            }
            default: {
                return 13.0;
            }
        }
    }
    
    public int getSpeed(final int level) {
        switch (level) {
            case 1:
            case 2: {
                return 0;
            }
            case 3:
            case 4: {
                return 1;
            }
            case 5: {
                return 2;
            }
            default: {
                return 0;
            }
        }
    }
    
    @Override
    public List<String> getInfo(final int level) {
        final List<String> lore = new ArrayList<String>();
        if (level == 1) {
            lore.add(" §8▪ §7瞬移到在§a" + this.getAttribute(level) + "§7格以内的指定玩家,");
            lore.add("   §7并获得5秒的速度§a" + StringUtils.level(this.getSpeed(level)) + "§7效果。");
            lore.add("   §7在激活速度" + StringUtils.level(this.getSpeed(level)) + "效果时,每次攻击");
            lore.add("   §7获得的能量减半");
            lore.add(" ");
            lore.add("§7冷却时间:§a5秒");
            return lore;
        }
        lore.add(" §8▪ §7瞬移到在§8" + this.getAttribute(level - 1) + " ➜");
        lore.add("   §a" + this.getAttribute(level) + "§7格以内的指定玩家,");
        if (level % 2 == 0) {
            lore.add("   §7并获得5秒的速度§8" + StringUtils.level(this.getSpeed(level)) + "§7效果。");
        }
        else {
            lore.add("   §7并获得5秒的速度§8" + StringUtils.level(this.getSpeed(level - 1)) + " ➜");
            lore.add("   §a" + StringUtils.level(this.getSpeed(level)) + "效果。");
        }
        lore.add("   §7在激活速度" + StringUtils.level(this.getSpeed(level)) + "效果时,每次攻击");
        lore.add("   §7获得的能量减半");
        return lore;
    }
    
    @Override
    public void upgrade(final GamePlayer gamePlayer) {
        final KitStatsContainer kitStats = gamePlayer.getPlayerStats().getKitStats(this.getClasses());
        kitStats.addSkillLevel();
    }
    
    @Override
    public int getPlayerLevel(final GamePlayer gamePlayer) {
        return gamePlayer.getPlayerStats().getKitStats(this.getClasses()).getSkillLevel();
    }
    
    @Override
    public boolean use(final GamePlayer gamePlayer, final KitStatsContainer kitStats) {
        final Player player = gamePlayer.getPlayer();
        if (Enderman.skillCooldown.getOrDefault(gamePlayer, 0) > 0) {
            player.sendMessage("§c技能正在冷却中！");
            return false;
        }
        Player target = null;
        for (final Block block : player.getLineOfSight(MainSkill.set, (int)this.getAttribute(kitStats.getSkillLevel()))) {
            for (final Player player2 : this.getNearbyPlayers(block.getLocation(), player, 2)) {
                if (target == null || player2.getLocation().distance(player.getLocation()) < target.getLocation().distance(player.getLocation())) {
                    target = player2;
                }
            }
        }
        if (target == null) {
            player.sendMessage("§c没有玩家在目标范围内！");
            return false;
        }
        player.teleport(target.getLocation());
        new BukkitRunnable() {
            public void run() {
                for (final Location location : LocationUtils.getCircle(player.getLocation(), 0.5, 20)) {
                    ParticleEffect.SPELL_WITCH.display(0.0f, 0.0f, 0.0f, 0.0f, 1, location, 30.0);
                }
                player.getWorld().playSound(player.getLocation(), Sound.ENDERMAN_TELEPORT, 1.0f, 1.0f);
            }
        }.runTaskLater((Plugin)MegaWalls.getInstance(), 5L);
        player.addPotionEffect(new PotionEffect(PotionEffectType.SPEED, 100, this.getSpeed(kitStats.getSkillLevel())));
        Enderman.skillCooldown.put(gamePlayer, 5);
        return true;
    }
    
    @Override
    public String getSkillTip(final GamePlayer gamePlayer) {
        return this.getClasses().getNameColor() + "§l" + this.getName() + " " + ((Enderman.skillCooldown.getOrDefault(gamePlayer, 0) == 0) ? ((gamePlayer.getEnergy() == 100) ? "§a§l✓" : "§c§l✕") : ("§c§l" + Enderman.skillCooldown.get(gamePlayer) + "秒"));
    }
    
    private List<Player> getNearbyPlayers(final Location location, final Player player, final int radius) {
        final List<Player> players = new ArrayList<Player>();
        final GamePlayer gamePlayer = GamePlayer.get(player.getUniqueId());
        for (final Player other : PlayerUtils.getNearbyPlayers(location, radius)) {
            final GamePlayer gameOther = GamePlayer.get(other.getUniqueId());
            if (!gameOther.isSpectator() && !gamePlayer.getGameTeam().isInTeam(gameOther)) {
                if (other.getLocation().distance(location) > radius) {
                    continue;
                }
                players.add(other);
            }
        }
        return players;
    }
    
    static {
        set = new HashSet<Material>();
        for (final Material material : Material.values()) {
            MainSkill.set.add(material);
        }
    }
}
